package vip.liux.front.infrastructure.security;

import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.K;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import vip.liux.core.current.ICurrentUser;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import static vip.liux.front.infrastructure.utils.JwtConverter.ClaimNames.*;


public class CurrentUser implements ICurrentUser<Long> {
    @Override
    public boolean isAuthenticated() {
        return getAuthentication() != null && StringUtils.isNotBlank(getAuthentication().getClaimAsString(USER_ID));
    }

    @Override
    public @Nullable Long getId() {
        return isAuthenticated() ? Long.parseLong(Objects.requireNonNull(getAuthentication()).getClaim(USER_ID)) : null;
    }

    @Override
    public @Nullable String getUserName() {
        return isAuthenticated() ? Objects.requireNonNull(getAuthentication()).getClaimAsString(USER_NAME) : null;
    }

    @Override
    public @Nullable String getName() {
        return isAuthenticated() ? Objects.requireNonNull(getAuthentication()).getClaimAsString(NAME) : null;
    }

    @Override
    public @Nullable String getSurName() {
        return isAuthenticated() ? Objects.requireNonNull(getAuthentication()).getClaimAsString(SUR_NAME) : null;
    }

    @Override
    public @Nullable String getPhoneNumber() {
        return isAuthenticated() ? Objects.requireNonNull(getAuthentication()).getClaimAsString(PHONE_NUMBER) : null;
    }

    @Override
    public boolean isPhoneNumberVerified() {
        return isAuthenticated() ? Objects.requireNonNull(getAuthentication()).getClaimAsBoolean(PHONE_NUMBER_VERIFIED) : false;
    }

    @Override
    public @Nullable String getEmail() {
        return isAuthenticated() ? Objects.requireNonNull(getAuthentication()).getClaimAsString(EMAIL) : null;
    }

    @Override
    public boolean isEmailVerified() {
        return isAuthenticated() ? Objects.requireNonNull(getAuthentication()).getClaimAsBoolean(EMAIL_VERIFIED) : false;
    }

    @Override
    public @Nullable String getTenantId() {
        throw new UnsupportedOperationException("Tenant ID is not supported in this implementation.");
    }

    @Override
    public @NotNull List<String> getRoles() {
        return isAuthenticated() ? List.copyOf(Objects.requireNonNull(getAuthentication()).getClaimAsStringList(ROLE)) : List.of();
    }

    @Override
    public @NotNull Map<String, Object> getAllClaims() {
        return Objects.requireNonNull(getAuthentication()).getClaims();
    }

    @Override
    public @Nullable K getClaim(String key, Class<K> clazz) {
        return clazz.cast(Objects.requireNonNull(getAuthentication()).getClaim(key));
    }

    @Override
    public @NotNull List<K> getClaims(String key, Class<K> clazz) {
        return Objects.requireNonNull(getAuthentication()).getClaimAsStringList(key).stream().map(clazz::cast).toList();
    }


    @Override
    public boolean isInRole(String roleName) {
        return false;
    }

    public Jwt getAuthentication() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            return null;
        }
        return (Jwt) authentication.getPrincipal();
    }

    public void setAuthentication(Authentication authentication) {
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }
}
